# -*- coding:utf8 -*-

import numpy as np

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *

from common import singleton
from logger import LOG


@singleton
class Camera(object):
    """
    相机控制类
    """
    def __init__(self):
        self.speed = 0.2

        self.eye_pos = np.array([0.0, 20.0, 20.0])    # x, y, z
        self.lookat_point = np.array([0, 0, 0])
        self.up_vector = np.array([0, 1, 0])

        self.mode = 0   # 0: 球面旋转模式  1:
        self.speed_angle = 2
        self.__v_angle = 45     # arctan(y/z)
        self.__h_angle = 90      # arctan(x/z)，注意坐标系的象限对应
        self.__radius = 20 * np.sqrt(2)

        self.init()

    def init(self):
        x, y, z = self.eye_pos[0], self.eye_pos[1], self.eye_pos[2]
        self.__v_angle = np.degrees(np.arctan(y/z))     # 弧度转角度
        if x == 0:
            self.__h_angle = 90     # 等于 270 也是可以的
        else:
            self.__h_angle = np.degrees(np.arctan(z/x))     # 注意z/x和x/z的差别
        self.__radius = np.sqrt(x*x + y*y + z*z)

        print (self.__v_angle, self.__h_angle, self.__radius)

    def update(self):
        """当lookat发生变化时，应该手动调用这个函数
        :return:
        """
        gluLookAt(
            self.eye_pos[0], self.eye_pos[1], self.eye_pos[2],
            self.lookat_point[0], self.lookat_point[1], self.lookat_point[2],
            self.up_vector[0], self.up_vector[1], self.up_vector[2]
        )
        # print (self.__v_angle, self.__h_angle, self.__radius)

    def eye_update(self):
        self.eye_pos[0] = self.__radius * np.cos(np.radians(self.__v_angle)) * np.cos(np.radians(self.__h_angle))
        self.eye_pos[1] = self.__radius * np.sin(np.radians(self.__v_angle))
        self.eye_pos[2] = self.__radius * np.cos(np.radians(self.__v_angle)) * np.sin(np.radians(self.__h_angle))
        self.update()
        # print self.__v_angle, self.__h_angle, self.__radius

    def move_up(self):
        if self.mode is 0:
            self.__v_angle += self.speed_angle

            if not self.__v_angle >= 90:
                self.eye_update()
            else:
                self.__v_angle = 90

    def move_down(self):
        if self.mode is 0:
            self.__v_angle -= self.speed_angle
            if not self.__v_angle <= 0:
                self.eye_update()
            else:
                self.__v_angle = 0

    def move_left(self):
        if self.mode is 0:
            self.__h_angle += self.speed_angle
            if self.__h_angle >= 360:
                self.__h_angle -= 360
            self.eye_update()

    def move_right(self):
        if self.mode is 0:
            self.__h_angle -= self.speed_angle
            if self.__h_angle <= 0:
                self.__h_angle += 360
            self.eye_update()
